package com.agri.utils;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

/**
 * 敏感数据加密工具类
 * 提供AES加密、SHA256、MD5等加密算法，以及数据脱敏功能
 * 用于保护用户敏感信息如身份证号、手机号等
 *
 * @author Agri-Fin-Sale Team
 * @version 1.0
 * @since 2025-10-30
 */
@Component
public class EncryptUtil {
    private static String aesKey;
    private static String aesIv;

    /**
     * 设置AES加密密钥
     * 通过Spring配置注入加密密钥
     *
     * @param key AES加密密钥（32字节）
     */
    @Value("${encrypt.aes-key}")
    public void setAesKey(String key) {
        EncryptUtil.aesKey = key;
    }

    /**
     * 设置AES初始化向量
     * 通过Spring配置注入初始化向量
     *
     * @param iv AES初始化向量（16字节）
     */
    @Value("${encrypt.aes-iv}")
    public void setAesIv(String iv) {
        EncryptUtil.aesIv = iv;
    }
    /**
     * AES加密方法
     * 使用CBC模式和PKCS5Padding对数据进行AES加密
     *
     * @param data 待加密的明文数据
     * @return String Base64编码的加密结果
     * @throws IllegalStateException 当加密配置未初始化时抛出
     * @throws RuntimeException 当加密过程发生异常时抛出
     */
    public static String encrypt(String data) {
        try {
            if (aesKey == null || aesIv == null) {
                throw new IllegalStateException("加密配置未初始化，请确保EncryptUtil已被Spring管理");
            }

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec keySpec = new SecretKeySpec(aesKey.getBytes(StandardCharsets.UTF_8), "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(aesIv.getBytes(StandardCharsets.UTF_8));

            cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
            byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
            return Base64.encodeBase64String(encrypted);
        } catch (Exception e) {
            throw new RuntimeException("AES加密失败", e);
        }
    }

    /**
     * AES解密方法
     * 使用CBC模式和PKCS5Padding对数据进行AES解密
     *
     * @param encryptedData Base64编码的加密数据
     * @return String 解密后的明文数据
     * @throws IllegalStateException 当加密配置未初始化时抛出
     * @throws RuntimeException 当解密过程发生异常时抛出
     */
    public static String decrypt(String encryptedData) {
        try {
            if (aesKey == null || aesIv == null) {
                throw new IllegalStateException("加密配置未初始化，请确保EncryptUtil已被Spring管理");
            }

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec keySpec = new SecretKeySpec(aesKey.getBytes(StandardCharsets.UTF_8), "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(aesIv.getBytes(StandardCharsets.UTF_8));

            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
            byte[] decrypted = cipher.doFinal(Base64.decodeBase64(encryptedData));
            return new String(decrypted, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException("AES解密失败", e);
        }
    }

    /**
     * 身份证号脱敏显示
     * 对加密后的身份证号进行脱敏处理，显示前6位和后4位，中间用****代替
     *
     * @param encryptedIdCard 加密后的身份证号字符串
     * @return String 脱敏后的身份证号（格式：前6位****后4位）
     */
    public static String maskIdCard(String encryptedIdCard) {
        if (encryptedIdCard == null || encryptedIdCard.length() < 10) {
            return encryptedIdCard;
        }
        return encryptedIdCard.substring(0, 6) + "****" + encryptedIdCard.substring(encryptedIdCard.length() - 4);
    }

    /**
     * 手机号脱敏显示
     * 对加密后的手机号进行脱敏处理，显示前3位和后4位，中间用****代替
     *
     * @param encryptedPhone 加密后的手机号字符串
     * @return String 脱敏后的手机号（格式：前3位****后4位）
     */
    public static String maskPhone(String encryptedPhone) {
        if (encryptedPhone == null || encryptedPhone.length() < 7) {
            return encryptedPhone;
        }
        return encryptedPhone.substring(0, 3) + "****" + encryptedPhone.substring(encryptedPhone.length() - 4);
    }

    /**
     * SHA256加密
     * @param data 待加密数据
     * @return 加密后的字符串
     */
    public static String sha256(String data) {
        return DigestUtils.sha256Hex(data);
    }

    /**
     * MD5加密
     * @param data 待加密数据
     * @return 加密后的字符串
     */
    public static String md5(String data) {
        return DigestUtils.md5Hex(data);
    }

    /**
     * 加盐加密
     * @param data 待加密数据
     * @param salt 盐值
     * @return 加密后的字符串
     */
    public static String sha256WithSalt(String data, String salt) {
        return sha256(data + salt);
    }
}